package org.jeecg.modules.qy_wechat.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.*;

/**
 * HTTP请求工具类
 */
@Slf4j
public class HttpUtils{

    private static final int CONNECT_TIMEOUT = 10000; // 连接超时时间(ms)
    private static final int SOCKET_TIMEOUT = 30000;   // 读取超时时间(ms)

    /**
     * 发送GET请求
     * @param url 请求URL
     * @return 响应结果
     */
    public static String sendGet(String url) {
        return sendGet(url, null, null);
    }

    /**
     * 发送GET请求
     * @param url 请求URL
     * @param headers 请求头
     * @return 响应结果
     */
    public static String sendGet(String url, Map<String, String> headers) {
        return sendGet(url, headers, null);
    }

    /**
     * 发送GET请求
     * @param url 请求URL
     * @param headers 请求头
     * @param params 请求参数
     * @return 响应结果
     */
    public static String sendGet(String url, Map<String, String> headers, Map<String, String> params) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        String result = "";

        try {
            // 创建HTTP客户端
            httpClient = createHttpClient(url);

            // 构建请求参数
            URIBuilder builder = new URIBuilder(url);
            if (params != null) {
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    builder.addParameter(entry.getKey(), entry.getValue());
                }
            }
            URI uri = builder.build();

            // 创建HTTP GET请求
            HttpGet httpGet = new HttpGet(uri);

            // 设置请求头
            setHeaders(httpGet, headers);

            // 设置请求配置
            RequestConfig requestConfig = RequestConfig.custom()
                    .setConnectTimeout(CONNECT_TIMEOUT)
                    .setSocketTimeout(SOCKET_TIMEOUT)
                    .build();
            httpGet.setConfig(requestConfig);

            // 执行请求
            response = httpClient.execute(httpGet);

            // 处理响应
            result = handleResponse(response);
        } catch (URISyntaxException | IOException e) {
            log.error("发送GET请求异常: {}", e.getMessage(), e);
        } finally {
            closeResources(httpClient, response);
        }

        return result;
    }

    /**
     * 发送POST请求
     * @param url 请求URL
     * @param json 请求JSON数据
     * @return 响应结果
     */
    public static String sendPost(String url, String json) {
        return sendPost(url, json, null);
    }

    /**
     * 发送POST请求
     * @param url 请求URL
     * @param json 请求JSON数据
     * @param headers 请求头
     * @return 响应结果
     */
    public static String sendPost(String url, String json, Map<String, String> headers) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        String result = "";

        try {
            // 创建HTTP客户端
            httpClient = createHttpClient(url);

            // 创建HTTP POST请求
            HttpPost httpPost = new HttpPost(url);

            // 设置请求头
            if (headers == null) {
                headers = new HashMap<>();
            }
            if (!headers.containsKey("Content-Type")) {
                headers.put("Content-Type", "application/json");
            }
            setHeaders(httpPost, headers);

            // 设置请求配置
            RequestConfig requestConfig = RequestConfig.custom()
                    .setConnectTimeout(CONNECT_TIMEOUT)
                    .setSocketTimeout(SOCKET_TIMEOUT)
                    .build();
            httpPost.setConfig(requestConfig);

            // 设置请求体
            if (json != null) {
                StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
                httpPost.setEntity(entity);
            }

            // 执行请求
            response = httpClient.execute(httpPost);

            // 处理响应
            result = handleResponse(response);
        } catch (IOException e) {
            log.error("发送POST请求异常: {}", e.getMessage(), e);
        } finally {
            closeResources(httpClient, response);
        }

        return result;
    }

    /**
     * 发送表单POST请求
     * @param url 请求URL
     * @param params 请求参数
     * @return 响应结果
     */
    public static String sendPostForm(String url, Map<String, String> params) {
        return sendPostForm(url, params, null);
    }

    /**
     * 发送表单POST请求
     * @param url 请求URL
     * @param params 请求参数
     * @param headers 请求头
     * @return 响应结果
     */
    public static String sendPostForm(String url, Map<String, String> params, Map<String, String> headers) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        String result = "";

        try {
            // 创建HTTP客户端
            httpClient = createHttpClient(url);

            // 创建HTTP POST请求
            HttpPost httpPost = new HttpPost(url);

            // 设置请求头
            if (headers == null) {
                headers = new HashMap<>();
            }
            if (!headers.containsKey("Content-Type")) {
                headers.put("Content-Type", "application/x-www-form-urlencoded");
            }
            setHeaders(httpPost, headers);

            // 设置请求配置
            RequestConfig requestConfig = RequestConfig.custom()
                    .setConnectTimeout(CONNECT_TIMEOUT)
                    .setSocketTimeout(SOCKET_TIMEOUT)
                    .build();
            httpPost.setConfig(requestConfig);

            // 设置表单参数
            if (params != null) {
                List<NameValuePair> paramList = new ArrayList<>();
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    paramList.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                }
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList, Consts.UTF_8);
                httpPost.setEntity(entity);
            }

            // 执行请求
            response = httpClient.execute(httpPost);

            // 处理响应
            result = handleResponse(response);
        } catch (IOException e) {
            log.error("发送表单POST请求异常: {}", e.getMessage(), e);
        } finally {
            closeResources(httpClient, response);
        }

        return result;
    }

    /**
     * 创建HttpClient（支持HTTP和HTTPS）
     * @param url 请求URL
     * @return HttpClient实例
     */
    private static CloseableHttpClient createHttpClient(String url) {
        try {
            if (url.startsWith("https")) {
                // 信任所有证书
                TrustStrategy trustStrategy = new TrustStrategy() {
                    @Override
                    public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                        return true;
                    }
                };

                SSLContext sslContext = SSLContexts.custom()
                        .loadTrustMaterial(null, trustStrategy)
                        .build();

                SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(
                        sslContext,
                        NoopHostnameVerifier.INSTANCE);

                return HttpClients.custom()
                        .setSSLSocketFactory(sslSocketFactory)
                        .build();
            } else {
                return HttpClients.createDefault();
            }
        } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
            log.error("创建HTTPS客户端异常: {}", e.getMessage(), e);
            return HttpClients.createDefault();
        }
    }

    /**
     * 设置请求头
     * @param httpRequestBase HTTP请求
     * @param headers 请求头
     */
    private static void setHeaders(HttpRequestBase httpRequestBase, Map<String, String> headers) {
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                httpRequestBase.setHeader(entry.getKey(), entry.getValue());
            }
        }
    }

    /**
     * 处理HTTP响应
     * @param response HTTP响应
     * @return 响应内容
     * @throws IOException 异常
     */
    private static String handleResponse(HttpResponse response) throws IOException {
        if (response == null) {
            return "";
        }

        StatusLine statusLine = response.getStatusLine();
        HttpEntity entity = response.getEntity();

        if (statusLine.getStatusCode() >= 300) {
            throw new ClientProtocolException("HTTP请求失败，状态码: " + statusLine.getStatusCode());
        }

        return entity != null ? EntityUtils.toString(entity, Consts.UTF_8) : "";
    }

    /**
     * 关闭资源
     * @param httpClient HTTP客户端
     * @param response HTTP响应
     */
    private static void closeResources(CloseableHttpClient httpClient, CloseableHttpResponse response) {
        try {
            if (response != null) {
                response.close();
            }
            if (httpClient != null) {
                httpClient.close();
            }
        } catch (IOException e) {
            log.error("关闭HTTP资源异常: {}", e.getMessage(), e);
        }
    }
}
